/**
 * Copyright (c) 2010-2011 Pierre Labatut
 *
 * This file is part of Space-Chronicles project.
 *
 * Space-Chronicles is free software: you can redistribute it and/or modify it
 * under the terms of its license which may be found in the accompanying
 * LICENSE file or <http://code.google.com/p/space-chronicles/>.
 */
package space.game;

import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import javax.media.opengl.GL3;
import javax.media.opengl.GL3bc;
import space.gl.Program;
import space.gl.Shader;
import space.stream.DataUtil;

/**
 *
 * @author Pierre
 */
public enum ShaderProgram {

    CHECKER("Checker", new String[]{}, new String[]{"res/checker.frag", "res/checker.vert"}),
    Z_CLAMP("ZClamp Only", new String[]{}, new String[]{"res/zClamp.frag", "res/zClamp.vert"}),
    DIFFUSE_MAP("View Diffuse Map", new String[]{},
    new String[]{"res/diffuseMapOnly.frag", "res/diffuseMapOnly.vert"}),
    NORMAL_MAP("View Normal Map", new String[]{},
    new String[]{"res/normalMapOnly.frag", "res/normalMapOnly.vert"}),
    VERTEX_LIGHT("Normal Only", new String[]{"no_diffuse_map"},
    new String[]{"res/normalShade.frag", "res/normalShade.vert"}),
    NORMAL_SHADE("Normal & Diffuse", new String[]{},
    new String[]{"res/normalShade.frag", "res/normalShade.vert"}),
    NORMAL_CSM_SHADE("Normal CSM Shade", new String[]{/*"debug_slice"*/},
    new String[]{"res/normalCSMShade.frag", "res/normalCSMShade.vert"}),
    TRAIL_SHADE("Trail Shade", new String[]{},
    new String[]{"res/trail.frag", "res/trail.vert", "res/trail.geom"}),
    ENGINE_GLOW("Engine Glow", new String[]{},
    new String[]{"res/engineGlow.frag", "res/engineGlow.vert"});

    private ShaderProgram(final String name, final String[] macros, final String[] absoluteResource) {
        if (name == null) {
            throw new IllegalArgumentException();
        }
        if (absoluteResource == null) {
            throw new IllegalArgumentException();
        }
        this.name = name;
        this.macros = macros;
        resources = absoluteResource;
    }
    final private String[] resources;
    final private String[] macros;
    final public String name;

    final public Program link(GL3bc gl) {
        final List<Shader> toLink = new ArrayList<Shader>();
        for (final String resource : resources) {
            final int type;
            if (resource.endsWith(".frag")) {
                type = GL3.GL_FRAGMENT_SHADER;
            } else if (resource.endsWith(".vert")) {
                type = GL3.GL_VERTEX_SHADER;
            } else if (resource.endsWith(".geom")) {
                type = GL3.GL_GEOMETRY_SHADER;
            } else {
                throw new IllegalArgumentException("only frag or vert extentions are allowed.");
            }
            final URL url = getClass().getClassLoader().getResource(resource);
            if (url == null) {
                throw new AssertionError(
                        "Resource '" + resource + "' not found in the current classpath");
            }
            final String vs_source = DataUtil.readUTF8(url);
            try {
                final Shader vs = new Shader(gl, type, macros, vs_source);
                toLink.add(vs);
            } catch (RuntimeException ex) {
                throw new RuntimeException("Failed to compile '" + resource + "'",ex);
            }
        }
        return new Program(gl, toLink);
    }
}
